﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Infrastructure.DAL.SeedWork.Extension;
using Infrastructure.Domain.SeedWork;
using Infrastructure.Domain.SeedWork.Core.Specification;
using Infrastructure.Repository.EntityFramework.Extension;
using Infrastructure.Repository.EntityFramework.Repository;

namespace Infrastructure.Repository.EntityFramework
{
    public class BaseDomainService : IBaseDomainService
    {
        private readonly IQueryableUnitOfWork _unitOfWork;

        public BaseDomainService(IQueryableUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        public TEntity Get<TEntity>(long id) where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            return repository.Get(id);
        }

        public void Add<TEntity>(TEntity entity) where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            repository.Add(entity);
        }

        public void Modify<TEntity>(TEntity entity) where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            repository.Modify(entity);
        }

        public void Remove<TEntity>(TEntity entity) where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            repository.Remove(entity);
        }

        public void Remove<TEntity>(long id) where TEntity : Entity
        {
            var entity = Get<TEntity>(id);
            Remove(entity);
        }

        public TEntity GetLast<TEntity>(ISpecification<TEntity> specification) where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            return repository.GetLast(specification);
        }

        public TEntity Single<TEntity>(ISpecification<TEntity> specification) where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            return repository.Single(specification);
        }


        public IEnumerable<TEntity> GetAll<TEntity>()
            where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            return repository.GetAll();
        }

        public IEnumerable<TEntity> GetAllMatching<TEntity>(ISpecification<TEntity> specification)
            where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            return repository.GetFiltered(specification.SatisfiedBy());
        }

        public IEnumerable<TEntity> GetPaged<TEntity, TProperty>(int pageIndex, int pageCount,
            Expression<Func<TEntity, TProperty>> orderByExpression, bool @ascending,
            ISpecification<TEntity> specification = null) where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            return repository.GetPaged(pageIndex, pageCount, orderByExpression, @ascending, specification);
        }


        public virtual IEnumerable<TEntity> GetFiltered<TEntity>(Expression<Func<TEntity, bool>> filter)
            where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            return repository.GetFiltered(filter);
        }

        public virtual void Merge<TEntity>(TEntity persisted, TEntity current)
            where TEntity : Entity
        {
            var repository = new Repository<TEntity>(_unitOfWork);
            repository.Merge(persisted, current);
        }
    }
}